#include <vector>
#include <random>
#include <iostream>
#include <iterator>
#include <type_traits>
#include <chrono>
#include <iomanip>
#include <string>

using std::copy;
using std::cout;
using std::is_integral_v;
using std::ostream_iterator;
using std::random_device;
using std::string;
using std::uniform_int_distribution;
using std::uniform_real_distribution;
using std::vector;

namespace Utils
{
    /**
     * @brief 左闭右开区间随机数
     *
     * @tparam T
     * @param begin     左界
     * @param end       右界
     * @param count     随机数个数
     * @return vector<T>
     */
    template <typename T>
    vector<T> getRandomNum(T begin, T end, size_t count)
    {
        vector<T> ret;
        random_device dr;
        if constexpr (is_integral_v<T>)
        {
            uniform_int_distribution<T> dis(begin, end);
            for (int i = 0; i < count; i++)
                ret.push_back(dis(dr));
        }
        else
        {
            uniform_real_distribution<T> dis(begin, end);
            for (int i = 0; i < count; i++)
                ret.push_back(dis(dr));
        }

        return ret;
    }

    template <typename T>
    void vectorPrint(const vector<T> &vec)
    {
        copy(vec.begin(), vec.end(), ostream_iterator<T>(cout, ", "));
        cout << "\n";
    }

    string getTimeStamp()
    {
        auto now = std::chrono::system_clock::now();
        auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()).count() % 1000;
        time_t localt = std::chrono::system_clock::to_time_t(now);
        std::stringstream ret;
        //%Y-%m-%d %H:%M:%S
        ret << std::put_time(localtime(&localt), "%F %T.") << std::setw(3) << std::setfill('0') << ms;
        return ret.str();
    }

    string getTimeDiff(std::chrono::_V2::system_clock::time_point &ptime)
    {
        auto now = std::chrono::system_clock::now();
        auto diff = std::chrono::duration_cast<std::chrono::milliseconds>(now - ptime).count();
        std::stringstream ret;
        ret << diff << " ms ";
        return ret.str();
    }

};